//Clase que representa a cada etiqueta
public class Etiqueta {
  private int  x1,y1;
  private float ancho,alto;
  private float radio;
  private int tipo;
  private ArrayList puntos;
  private String nombre;
  private int offsetantx=0;
  private int offsetanty=0;
  //Constructor d ela etiqueta cuadrado
  public Etiqueta(int x1,int y1,float ancho,float alto,String nombre) {
    this.x1=x1;
    this.y1=y1;
    this.ancho = ancho;
    this.alto = alto;
    this.tipo = 1;
    this.nombre = nombre;
  }
  //Constructor de la etiqueta punto
  public Etiqueta(int x1,int y1,String nombre) {
    this.x1=x1;
    this.y1=y1;
    this.tipo = 4;
    this.nombre = nombre;
  }
  //Constructor de la etiqueta circular
  public Etiqueta(int x1,int y1, float radio,String nombre) {
    this.x1=x1;
    this.y1=y1;
    this.radio=radio;
    this.tipo=2;
    this.nombre = nombre;
  }
  //Constructor de la estiqueta poligono
  public Etiqueta(ArrayList puntos,String nombre,int tipo) {
    this.puntos = puntos;
    this.tipo=tipo;
    this.nombre = nombre;
  }
  //Funcion que pone un nombre a la etiqueta
  public void setNombre(String nombre) {
    this.nombre = nombre;
  }
  //Funcion que mueve una etiqueta
  public void mover(int x, int y) {
    if(tipo ==1 || tipo == 2 || tipo ==4) {
      this.x1+=x;
      this.y1+=y;
    }
    else if( tipo == 3 ) {

      Iterator i = puntos.iterator();
      int[] punto;
      while(i.hasNext()) {
        punto = (int[]) i.next();
        punto[0]+=x;
        punto[1]+=y;
      }
    }
  }
  //Funcion que mira si una etiqueta ha sido presionada
  public boolean isPressed(int offsetx,int offsety,float zoom,float dragX,float dragY) {
    int posx,posy;
    switch(tipo) {
    case 1:
      posx = x1+(width -offsetx)/2 ;
      posy = y1+(height -offsety)/2;
      if(mouseX > posx && mouseX < posx + ancho && mouseY > posy && mouseY < posy+alto) {
        return true;
      }
      break;
    case 2:
      posx = x1+(width -offsetx)/2 ;
      posy = y1+(height -offsety)/2 ;
      if(mouseX > posx-radio && mouseX < posx + radio  && mouseY > posy-radio && mouseY < posy+radio) {
        return true;
      }
      break;
    }
    return false;
  }
  //Funcion que muestra la etiqueta
  void display(int offsetx,int offsety,boolean elim,float zoom,float zoomy,float dragX,float dragY) {
    noFill();
    stroke(255);
    int posx,posy;
    int x1=0;
    int x2=0;
    int y1=0;
    int y2=0;
    float px=0;
    float py=0;  
      Iterator i;
    switch(tipo) {      
    case 1:
    px= (this.x1) * zoom;
    py = (this.y1) * zoomy;
    float pw = ancho * zoom;
    float ph = alto * zoomy;   
      posx = (int)((px+(width -offsetx)/2));
      posy = (int)((py+(height -offsety)/2));
      if(elim) {
        stroke(255,0,0);
      }
      rect(posx+dragX ,posy+dragY,pw,ph);
      break;
    case 2:    
       px = (this.x1) * zoom;
       py = (this.y1) * zoomy;
      float pr = this.radio * zoom;
      float pr2 = this.radio  * zoomy;
      posx = (int)(px+(width -offsetx)/2);
      posy = (int)(py+(height -offsety)/2);
      if(elim) {
        stroke(255,0,0);
        elim=!elim;
      }
      ellipse(posx+dragX,posy+dragY,pr*2,pr2*2);
      break;
    case 3:
      if(elim) {
        stroke(255,0,0);
      }
       i = puntos.iterator();      
      int[] p = (int[]) i.next();
      x1=(int)((p[0])*zoom);
      y1=(int)((p[1])*zoomy);
      while(i.hasNext()) {
        p = (int[]) i.next();
         x2=(int)((p[0])*zoom);
      y2=(int)((p[1])*zoomy);        
        line(x1+(width-offsetx)/2+dragX ,y1+(height-offsety)/2+dragY ,x2+(width-offsetx)/2+dragX ,y2+(height-offsety)/2+dragY );
        x1=x2;
        y1=y2;
      }
      p =(int[]) puntos.get(0);
      x2=(int)((p[0])*zoom);
      y2=(int)((p[1])*zoomy);
      line(x1+(width-offsetx)/2+dragX  ,y1+(height-offsety)/2+dragY ,x2+(width-offsetx)/2+dragX  ,y2+(height-offsety)/2+dragY  );
      break;
    case 4:
      if(elim) {
        fill(255,0,0);
        stroke(255,0,0);
      }
      else {
        fill(255);
      }
      px = (this.x1)*zoom;
      py = (this.y1)*zoomy;
      rect(px+(width-offsetx)/2+dragX ,py+(height-offsety)/2+dragY,1,1);
      break;            
      case 5:
      if(elim) {
        stroke(255,0,0);        
      }
      i = puntos.iterator();      
      int[] p2;      
      while(i.hasNext()) {
        p2 = (int[]) i.next();
        x2=(int)((p2[0])*zoom);
        y2=(int)((p2[1])*zoomy);
        rect(x2+(width-offsetx)/2+dragX ,y2+(height-offsety)/2+dragY,1,1);        
      }    
      break;
    }
  }

  //Getters
  int getX() {
    return x1;
  }
  int getY() {
    return y1;
  }
  float getRadio() {
    return radio;
  }
  float getAncho() {
    return ancho;
  }
  float getAlto() {
    return alto;
  }
  //Funcion que retorna la distancia minima entre un vertice de la etiqueta y el mouse
  float getMinDist(int offsetx,int offsety,float zoom,float zoomy,float dragX,float dragY) {
    float dista =0;
    switch(tipo) {
    case 1:      
      dista = abs(((((mouseX-dragX)- (width-offsetx)/2))/zoom)-this.x1);
      dista = abs(((((mouseX-dragX)- (width-offsetx)/2))/zoom)-(this.x1+this.ancho))<dista?abs(((((mouseX-dragX)- (width-offsetx)/2))/zoom)-(this.x1+this.ancho)):dista;
      dista = abs(((((mouseY-dragY)- (height-offsety)/2))/zoomy)-this.y1)<dista?abs(((((mouseY-dragY)- (height-offsety)/2))/zoomy)-this.y1):dista;
      dista = abs(((((mouseY-dragY)- (height-offsety)/2))/zoomy)-(this.y1+this.alto))<dista?abs(((((mouseY-dragY)- (height-offsety)/2))/zoomy)-(this.y1+this.alto)):dista;
      return dista;
    case 2:
      int x2 = (int)((((mouseX-dragX) -((width-offsetx)/2)))/zoom);
      int y2 = (int)((((mouseY-dragY) -((height-offsety)/2)))/zoomy);
      int rad = (int)(sqrt(pow((int)(x2-x1),2)+pow((int)(y2-y1),2)));
      return abs(radio-rad);
    case 3:
      Iterator i = puntos.iterator();
      int[] punto = (int[]) i.next();
      int[] punto2 = (int[]) i.next();
      int[] primerPunto = punto;
      float m=0;
      float b=0;
      if(punto[0] - punto2[0] == 0f) {
        //Vertical
        dista = abs((((mouseX-dragX)- (width-offsetx)/2)/zoom)-punto[0]);
      }
      else {
        m = (float)(punto2[1]-punto[1])/(punto2[0]-punto[0]);

        b = (float)punto[1] -1*m*punto[0];
        if(m==0f) {
          //Horizontal
          dista=abs(((((mouseY-dragY)- (height-offsety)/2)/zoomy)-punto[1]));
        }
        else {
          dista = abs((m*((((mouseX-dragX)-(width-offsetx)/2))/zoomy))-((((mouseY-dragY)-(height-offsety)/2))/zoomy)+b);
          dista /=sqrt(pow(m,2)+1);
        }
      }
      float dista2=100000000;
      while(i.hasNext()) {
        punto = punto2;
        punto2 = (int[]) i.next();
        if(punto[0] - punto2[0] == 0f) {
          //Vertical
          dista2= abs(((((mouseX-dragX)- (width-offsetx)/2))/zoom)-punto[0]);
          dista= dista2<dista?dista2:dista;
        }
        else {
          m =(float) (punto2[1]-punto[1])/(punto2[0]-punto[0]);
          b = (float)punto[1] -1*m*punto[0];
          if(m==0f) {
            //Horizontal
            dista2=abs(((((mouseY-dragY)- (height-offsety)/2))/zoomy)-punto[1]);
            dista= dista2<dista?dista2:dista;
          }
          else {
            dista2 = abs((m*((((mouseX-dragX)-(width-offsetx)/2))/zoom))-((((mouseY-dragY)-(height-offsety)/2))/zoomy)+b);
            dista2 /=sqrt(pow(m,2)+1);
            dista= dista2<dista?dista2:dista;
          }
        }
      }
      punto = primerPunto;
      if(punto[0] - punto2[0] == 0f) {
        //Vertical
        dista2= abs(((((mouseX-dragX)- (width-offsetx)/2))/zoom)-punto[0]);
        dista= dista2<dista?dista2:dista;
      }
      else {
        m =(float) (punto2[1]-punto[1])/(punto2[0]-punto[0]);
        b = (float)punto[1] -1*m*punto[0];
        if(m==0f) {
          //Horizontal
          dista2=abs(((((mouseY-dragY)- (height-offsety)/2))/zoomy)-punto[1]);
          dista= dista2<dista?dista2:dista;
        }
        else {
          dista2 = abs((m*((((mouseX-dragX)-(width-offsetx)/2))/zoom))-((((mouseY-dragY)-(height-offsety)/2))/zoomy+b));
          dista2 /=sqrt(pow(m,2)+1);
          dista= dista2<dista?dista2:dista;
        }
      }
      return dista;
    case 4:
      return sqrt(pow(((((mouseX-dragX)-(width-offsetx)/2))/zoom)-x1,2)+pow(((((mouseY-dragY)-(height-offsety)/2))/zoomy)-y1,2));      
      case 5:      
      i = puntos.iterator();
      int[] p = (int[])i.next();
      float dist = sqrt(pow(((((mouseX-dragX)-(width-offsetx)/2))/zoom)-p[0],2)+pow(((((mouseY-dragY)-(height-offsety)/2))/zoomy)-p[1],2));      
      while(i.hasNext()){
       p=(int[])i.next();
       float distmp =  sqrt(pow(((((mouseX-dragX)-(width-offsetx)/2))/zoom)-p[0],2)+pow(((((mouseY-dragY)-(height-offsety)/2))/zoomy)-p[1],2));
       dist = distmp < dist? distmp:dist;
      }
      return dist;      
    }    
    return 10000;
  }
  //Funcion que agrega la parte del arbol xml de la etiqueta para guardarla
  public void agregarTree(PrintWriter output) {
    switch(tipo) {
    case 1:
      output.print("\t\t<Square ");
      output.print("name=\""+this.nombre+"\" ");
      output.print("x=\""+this.x1+"\" ");
      output.print("y=\""+this.y1+"\" ");
      output.print("height=\""+this.alto+"\" ");
      output.println("width=\""+this.ancho+"\" />");
      println(x1+" "+y1+" "+ancho+" "+alto);
      break;
    case 2:
      output.print("\t\t<Circle ");
      output.print("name=\""+this.nombre+"\" ");
      output.print("x=\""+this.x1+"\" ");
      output.print("y=\""+this.y1+"\" ");
      output.println("radio=\""+this.radio+"\" />");
      break;
    case 3:
      output.println("\t\t<Poligon name=\""+this.nombre+"\">");
      Iterator i = puntos.iterator();
      while(i.hasNext()) {
        int[] p = (int[]) i.next();
        output.print("\t\t\t<Line x=\""+p[0]);
        output.println("\" y=\""+p[1]+"\" />");
      }
      output.println("\t\t</Poligon>");
      break;
    case 4:
      output.print("\t\t<Point ");
      output.print("name=\""+this.nombre+"\" ");
      output.print("x=\""+this.x1+"\" ");
      output.println("y=\""+this.y1+"\" />");
      break;      
      case 5:
      output.println("\t\t<Pointsec name=\""+this.nombre+"\">");
       i = puntos.iterator();
      while(i.hasNext()) {
        int[] p = (int[]) i.next();
        output.print("\t\t\t<Point x=\""+p[0]);
        output.println("\" y=\""+p[1]+"\" />");
      }
      output.println("\t\t</Pointsec>");
      break;
    }
  }
  //Getter
  public String getNombre() {
    return this.nombre;
  }
}

